/**
 * createStore，创建store实例
 * 包含三个方法
 * dispatch、subscribe、getState
 * 三个参数
 * reducer、preloadState、enhancer
 * 
 * enhancer对store实例进行功能上的增强
 */
function createStore (reducer, preloadState, enhancer) {
  // 限制reducer的类型
  if (typeof reducer !== 'function') throw Error('reducer必须是一个函数')
  // 判断enhancer是否传递
  if (typeof enhancer !== 'undefined') {
    if (typeof enhancer === 'function') {
      // 如果enhancer是函数，则调用这个函数，并传递createStore
      // enhancer应该返回一个函数，调用返回的这个函数，将reducer和preloadState传递进去，得到新的增强过的store实例，并进行返回
      return enhancer(createStore)(reducer, preloadState)
    }
  }
  // 定义状态
  var currentState = preloadState
  // 存放订阅者函数
  var currentListeners = []
  // 获取状态
  function getState() {
    return currentState
  }
  // 触发action
  function dispatch(action) {
    if(!isPlainObject(action)) throw Error('action必须是一个对象')

    if(typeof action.type === 'undefined') throw Error('action必须有type属性')
    // 获得经过reducer处理的状态
    currentState = reducer(currentState, action)
    // 遍历订阅者并调用
    for(let i = 0; i < currentListeners.length; i++) {
      let listener = currentListeners[i]
      listener()
    }
  }
  // 订阅状态
  function subscribe(listener) {
    currentListeners.push(listener)
  }

  return {
    getState,
    dispatch,
    subscribe
  }
}

// 判断参数是否为对象
function isPlainObject(obj) {
  if (typeof obj !== 'object' || obj === null) return false

  let proto = obj
  while (Object.getPrototypeOf(proto) !== null) {
    proto = Object.getPrototypeOf(proto)
  }
  return Object.getPrototypeOf(obj) === proto
}